/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "hks_access_control_rsa_sign_verify_test.h"
#include "hks_access_control_rsa_sign_verify_test_common.h"

#include <gtest/gtest.h>

using namespace testing::ext;
namespace Unittest::RsaSignVerify {
class HksRsaSignVerifyPart1Test : public testing::Test {
public:
    static void SetUpTestCase(void);

    static void TearDownTestCase(void);

    void SetUp();

    void TearDown();
};

void HksRsaSignVerifyPart1Test::SetUpTestCase(void)
{
}

void HksRsaSignVerifyPart1Test::TearDownTestCase(void)
{
}

void HksRsaSignVerifyPart1Test::SetUp()
{
}

void HksRsaSignVerifyPart1Test::TearDown()
{
}

/*
mock:
secureUid = 0
enrollinfo: authtype = PIN, enrolledId = 0
*/
static struct HksParam g_genParamsTest001[] = {
    {
        .tag = HKS_TAG_ALGORITHM,
        .uint32Param = HKS_ALG_RSA
    }, {
        .tag = HKS_TAG_PURPOSE,
        .uint32Param = HKS_KEY_PURPOSE_SIGN | HKS_KEY_PURPOSE_VERIFY
    }, {
        .tag = HKS_TAG_KEY_SIZE,
        .uint32Param = HKS_RSA_KEY_SIZE_512
    }, {
        .tag = HKS_TAG_PADDING,
        .uint32Param = HKS_PADDING_PKCS1_V1_5
    }, {
        .tag = HKS_TAG_DIGEST,
        .uint32Param = HKS_DIGEST_MD5
    }, {
        .tag = HKS_TAG_KEY_SECURE_ACCESS_TYPE,
        .uint32Param = HKS_SECURE_ACCESS_INVALID_CLEAR_PASSWORD
    }, {
        .tag =  HKS_TAG_USER_AUTH_TYPE ,                         
        .uint32Param =  HKS_USER_AUTH_TYPE_PIN                   
    }
};

static struct HksParam g_signParamsTest002[] = {
    {
        .tag = HKS_TAG_ALGORITHM,
        .uint32Param = HKS_ALG_RSA
    }, {
        .tag = HKS_TAG_PURPOSE,
        .uint32Param = HKS_KEY_PURPOSE_SIGN
    }, {
        .tag = HKS_TAG_KEY_SIZE,
        .uint32Param = HKS_RSA_KEY_SIZE_512
    }, {
        .tag = HKS_TAG_PADDING,
        .uint32Param = HKS_PADDING_PKCS1_V1_5
    }, {
        .tag = HKS_TAG_DIGEST,
        .uint32Param = HKS_DIGEST_MD5
    }, {
        .tag = HKS_TAG_CHALLENGE_TYPE,         
        .uint32Param = HKS_CHALLENGE_TYPE_NORMAL 
    }
};

static struct HksParam g_verifyParamsTest002[] = {
    {
        .tag = HKS_TAG_ALGORITHM,
        .uint32Param = HKS_ALG_RSA
    }, {
        .tag = HKS_TAG_PURPOSE,
        .uint32Param = HKS_KEY_PURPOSE_VERIFY
    }, {
        .tag = HKS_TAG_KEY_SIZE,
        .uint32Param = HKS_RSA_KEY_SIZE_512
    }, {
        .tag = HKS_TAG_PADDING,
        .uint32Param = HKS_PADDING_PKCS1_V1_5
    }, {
        .tag = HKS_TAG_DIGEST,
        .uint32Param = HKS_DIGEST_MD5
    }, {
        .tag = HKS_TAG_CHALLENGE_TYPE,         
        .uint32Param = HKS_CHALLENGE_TYPE_NORMAL 
    }
};

/*
mock:
secureUid = 0
enrollinfo: authtype = PIN, enrolledId = 0
*/
static struct HksParam g_genParamsTest002[] = {
    {
        .tag = HKS_TAG_ALGORITHM,
        .uint32Param = HKS_ALG_RSA
    }, {
        .tag = HKS_TAG_PURPOSE,
        .uint32Param = HKS_KEY_PURPOSE_SIGN | HKS_KEY_PURPOSE_VERIFY
    }, {
        .tag = HKS_TAG_KEY_SIZE,
        .uint32Param = HKS_RSA_KEY_SIZE_512
    }, {
        .tag = HKS_TAG_PADDING,
        .uint32Param = HKS_PADDING_PKCS1_V1_5
    }, {
        .tag = HKS_TAG_DIGEST,
        .uint32Param = HKS_DIGEST_SHA1
    }, {
        .tag = HKS_TAG_KEY_SECURE_ACCESS_TYPE,
        .uint32Param = HKS_SECURE_ACCESS_INVALID_CLEAR_PASSWORD
    }, {
        .tag =  HKS_TAG_USER_AUTH_TYPE ,                         
        .uint32Param =  HKS_USER_AUTH_TYPE_PIN                   
    }
};

static struct HksParam g_signParamsTest002[] = {
    {
        .tag = HKS_TAG_ALGORITHM,
        .uint32Param = HKS_ALG_RSA
    }, {
        .tag = HKS_TAG_PURPOSE,
        .uint32Param = HKS_KEY_PURPOSE_SIGN
    }, {
        .tag = HKS_TAG_KEY_SIZE,
        .uint32Param = HKS_RSA_KEY_SIZE_512
    }, {
        .tag = HKS_TAG_PADDING,
        .uint32Param = HKS_PADDING_PKCS1_V1_5
    }, {
        .tag = HKS_TAG_DIGEST,
        .uint32Param = HKS_DIGEST_SHA1
    }, {
        .tag = HKS_TAG_CHALLENGE_TYPE,         
        .uint32Param = HKS_CHALLENGE_TYPE_NORMAL 
    }
};

static struct HksParam g_verifyParamsTest002[] = {
    {
        .tag = HKS_TAG_ALGORITHM,
        .uint32Param = HKS_ALG_RSA
    }, {
        .tag = HKS_TAG_PURPOSE,
        .uint32Param = HKS_KEY_PURPOSE_VERIFY
    }, {
        .tag = HKS_TAG_KEY_SIZE,
        .uint32Param = HKS_RSA_KEY_SIZE_512
    }, {
        .tag = HKS_TAG_PADDING,
        .uint32Param = HKS_PADDING_PKCS1_V1_5
    }, {
        .tag = HKS_TAG_DIGEST,
        .uint32Param = HKS_DIGEST_SHA1
    }, {
        .tag = HKS_TAG_CHALLENGE_TYPE,         
        .uint32Param = HKS_CHALLENGE_TYPE_NORMAL 
    }
};

/*
mock:
secureUid = 0
enrollinfo: authtype = PIN, enrolledId = 0
*/
static struct HksParam g_genParamsTest003_1[] = {
    {
        .tag = HKS_TAG_ALGORITHM,
        .uint32Param = HKS_ALG_RSA
    }, {
        .tag = HKS_TAG_PURPOSE,
        .uint32Param = HKS_KEY_PURPOSE_SIGN | HKS_KEY_PURPOSE_VERIFY
    }, {
        .tag = HKS_TAG_KEY_SIZE,
        .uint32Param = HKS_RSA_KEY_SIZE_1024
    }, {
        .tag = HKS_TAG_PADDING,
        .uint32Param = HKS_PADDING_PSS
    }, {
        .tag = HKS_TAG_DIGEST,
        .uint32Param = HKS_DIGEST_SHA224
    }, {
        .tag = HKS_TAG_KEY_SECURE_ACCESS_TYPE,
        .uint32Param = HKS_SECURE_ACCESS_INVALID_CLEAR_PASSWORD
    }, {
        .tag =  HKS_TAG_USER_AUTH_TYPE ,                         
        .uint32Param =  HKS_USER_AUTH_TYPE_PIN                   
    }
};

static struct HksParam g_genParamsTest003_2[] = {
    {
        .tag = HKS_TAG_ALGORITHM,
        .uint32Param = HKS_ALG_RSA
    }, {
        .tag = HKS_TAG_PURPOSE,
        .uint32Param = HKS_KEY_PURPOSE_SIGN | HKS_KEY_PURPOSE_VERIFY
    }, {
        .tag = HKS_TAG_KEY_SIZE,
        .uint32Param = HKS_RSA_KEY_SIZE_2048
    }, {
        .tag = HKS_TAG_PADDING,
        .uint32Param = HKS_PADDING_PKCS1_V1_5
    }, {
        .tag = HKS_TAG_DIGEST,
        .uint32Param = HKS_DIGEST_NONE
    }, {
        .tag = HKS_TAG_KEY_SECURE_ACCESS_TYPE,
        .uint32Param = HKS_SECURE_ACCESS_INVALID_CLEAR_PASSWORD
    }, {
        .tag =  HKS_TAG_USER_AUTH_TYPE ,                         
        .uint32Param =  HKS_USER_AUTH_TYPE_PIN                   
    }
};

static struct HksParam g_signParamsTest003_1[] = {
    {
        .tag = HKS_TAG_ALGORITHM,
        .uint32Param = HKS_ALG_RSA
    }, {
        .tag = HKS_TAG_PURPOSE,
        .uint32Param = HKS_KEY_PURPOSE_SIGN
    },  {
        .tag = HKS_TAG_KEY_SIZE,
        .uint32Param = HKS_RSA_KEY_SIZE_1024
    }, {
        .tag = HKS_TAG_PADDING,
        .uint32Param = HKS_PADDING_PSS
    }, {
        .tag = HKS_TAG_DIGEST,
        .uint32Param = HKS_DIGEST_SHA224
    }, {
        .tag = HKS_TAG_CHALLENGE_TYPE,         
        .uint32Param = HKS_CHALLENGE_TYPE_CUSTOM
    }
};

static struct HksParam g_signParamsTest003_2[] = {
    {
        .tag = HKS_TAG_ALGORITHM,
        .uint32Param = HKS_ALG_RSA
    }, {
        .tag = HKS_TAG_PURPOSE,
        .uint32Param = HKS_KEY_PURPOSE_SIGN
    },  {
        .tag = HKS_TAG_KEY_SIZE,
        .uint32Param = HKS_RSA_KEY_SIZE_2048
    }, {
        .tag = HKS_TAG_PADDING,
        .uint32Param = HKS_PADDING_PKCS1_V1_5
    }, {
        .tag = HKS_TAG_DIGEST,
        .uint32Param = HKS_DIGEST_NONE
    }, {
        .tag = HKS_TAG_CHALLENGE_TYPE,         
        .uint32Param = HKS_CHALLENGE_TYPE_CUSTOM 
    }
};

static struct HksParam g_verifyParamsTest003_1[] = {
    {
        .tag = HKS_TAG_ALGORITHM,
        .uint32Param = HKS_ALG_RSA
    }, {
        .tag = HKS_TAG_PURPOSE,
        .uint32Param = HKS_KEY_PURPOSE_VERIFY
    },  {
        .tag = HKS_TAG_KEY_SIZE,
        .uint32Param = HKS_RSA_KEY_SIZE_1024
    }, {
        .tag = HKS_TAG_PADDING,
        .uint32Param = HKS_PADDING_PSS
    }, {
        .tag = HKS_TAG_DIGEST,
        .uint32Param = HKS_DIGEST_SHA224
    }, {
        .tag = HKS_TAG_CHALLENGE_TYPE,         
        .uint32Param = HKS_CHALLENGE_TYPE_CUSTOM
    }
};

static struct HksParam g_verifyParamsTest003_2[] = {
    {
        .tag = HKS_TAG_ALGORITHM,
        .uint32Param = HKS_ALG_RSA
    }, {
        .tag = HKS_TAG_PURPOSE,
        .uint32Param = HKS_KEY_PURPOSE_VERIFY
    }, {
        .tag = HKS_TAG_KEY_SIZE,
        .uint32Param = HKS_RSA_KEY_SIZE_2048
    }, {
        .tag = HKS_TAG_PADDING,
        .uint32Param = HKS_PADDING_PKCS1_V1_5
    }, {
        .tag = HKS_TAG_DIGEST,
        .uint32Param = HKS_DIGEST_NONE
    }, {
        .tag = HKS_TAG_CHALLENGE_TYPE,         
        .uint32Param = HKS_CHALLENGE_TYPE_CUSTOM 
    }
};

/**
 * @tc.name: HksRsaSignVerifyPart1Test.HksRsaSignVerifyPart1Test001
 * @tc.desc: alg-RSA pur-Sign pad-PKCS1_V1_5 digest-MD5.
 * @tc.type: FUNC
 */
HWTEST_F(HksRsaSignVerifyTest, HksAcRsaSignVerifyTest001, TestSize.Level0)
{
    int32_t ret = HKS_FAILURE;
    const char *keyAliasString = "HksRSASignVerifyKeyAliasTest001";
    struct HksParamSet *genParamSet = nullptr;
    struct HksParamSet *signParamSet = nullptr;
    struct HksParamSet *verifyParamSet = nullptr;
    uint64_t secureUid = 0;
    uint64_t enrolledId = 0;
    uint64_t time = 0;

    ret = InitParamSet(&genParamSet, g_genParamsTest001, sizeof(g_genParamsTest001) / sizeof(HksParam));
    EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet failed.";
    ret = InitParamSet(&signParamSet, g_signParamsTest001, sizeof(g_signParamsTest001) / sizeof(HksParam));
    EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet failed.";
    ret = InitParamSet(&verifyParamSet, g_verifyParamsTest001, sizeof(g_verifyParamsTest001) / sizeof(HksParam));
    EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet failed.";

    /* Generate Key */
    struct HksBlob keyAlias = {strlen(keyAliasString), (uint8_t *)keyAliasString};

    if ((genParamSet != nullptr) || (signParamSet != nullptr) || (verifyParamSet != nullptr)) {
        ret = HksAcRsaSignVerifyTestNormalCase(keyAlias, genParamSet, signParamSet, verifyParamSet, secureUid, enrolledId, time);
    }
    EXPECT_EQ(ret, HKS_SUCCESS) << "Three stage failed.";

    /* Delete Key */
    ret = HksDeleteKey(&keyAlias, genParamSet);
    EXPECT_EQ(ret, HKS_SUCCESS) << "DeleteKey failed.";

    HksFreeParamSet(&genParamSet);
    HksFreeParamSet(&signParamSet);
    HksFreeParamSet(&verifyParamSet);
}

HWTEST_F(HksRsaSignVerifyTest, HksAcRsaSignVerifyTest002, TestSize.Level0)
{
    int32_t ret = HKS_FAILURE;
    const char *keyAliasString = "HksRSASignVerifyKeyAliasTest001";
    struct HksParamSet *genParamSet = nullptr;
    struct HksParamSet *signParamSet = nullptr;
    struct HksParamSet *verifyParamSet = nullptr;
    uint64_t secureUid = 1;
    uint64_t enrolledId = 0;
    uint64_t time = 0;

    ret = InitParamSet(&genParamSet, g_genParamsTest002, sizeof(g_genParamsTest002) / sizeof(HksParam));
    EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet failed.";
    ret = InitParamSet(&signParamSet, g_signParamsTest002, sizeof(g_signParamsTest002) / sizeof(HksParam));
    EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet failed.";
    ret = InitParamSet(&verifyParamSet, g_verifyParamsTest002, sizeof(g_verifyParamsTest002) / sizeof(HksParam));
    EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet failed.";

    /* Generate Key */
    struct HksBlob keyAlias = {strlen(keyAliasString), (uint8_t *)keyAliasString};

    if ((genParamSet != nullptr) || (signParamSet != nullptr) || (verifyParamSet != nullptr)) {
        ret = HksAcRsaSignVerifyTestAbNormalCase(keyAlias, genParamSet, signParamSet, verifyParamSet, secureUid, enrolledId, time);
    }
    EXPECT_NE(ret, HKS_SUCCESS) << "Three stage failed.";

    /* Delete Key */
    ret = HksDeleteKey(&keyAlias, genParamSet);
    EXPECT_EQ(ret, HKS_SUCCESS) << "DeleteKey failed.";

    HksFreeParamSet(&genParamSet);
    HksFreeParamSet(&signParamSet);
    HksFreeParamSet(&verifyParamSet);
}

HWTEST_F(HksRsaSignVerifyTest, HksAcRsaSignVerifyTest003, TestSize.Level0)
{
    int32_t ret = HKS_FAILURE;
    const char *keyAliasString1 = "HksRSASignVerifyKeyAliasTest003_1";
    const char *keyAliasString2 = "HksRSASignVerifyKeyAliasTest003_2";
    struct HksParamSet *genParamSet1 = nullptr;
    struct HksParamSet *signParamSet1 = nullptr;
    struct HksParamSet *verifyParamSet1 = nullptr;
    struct HksParamSet *genParamSet2 = nullptr;
    struct HksParamSet *signParamSet2 = nullptr;
    struct HksParamSet *verifyParamSet2 = nullptr;
    uint64_t secureUid = 0;
    uint64_t enrolledId = 0;
    uint64_t time = 0;

    ret = InitParamSet(&genParamSet1, g_genParamsTest003_1, sizeof(g_genParamsTest003_1) / sizeof(HksParam));
    EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet failed.";
    ret = InitParamSet(&signParamSet1, g_signParamsTest003_1, sizeof(g_signParamsTest003_1) / sizeof(HksParam));
    EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet failed.";
    ret = InitParamSet(&verifyParamSet1, g_verifyParamsTest003_1, sizeof(g_verifyParamsTest003_1) / sizeof(HksParam));
    EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet failed.";
    ret = InitParamSet(&genParamSet2, g_genParamsTest003_2, sizeof(g_genParamsTest003_2) / sizeof(HksParam));
    EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet failed.";
    ret = InitParamSet(&signParamSet2, g_signParamsTest003_2, sizeof(g_signParamsTest003_2) / sizeof(HksParam));
    EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet failed.";
    ret = InitParamSet(&verifyParamSet2, g_verifyParamsTest003_2, sizeof(g_verifyParamsTest003_2) / sizeof(HksParam));
    EXPECT_EQ(ret, HKS_SUCCESS) << "InitParamSet failed.";

    /* Generate Key */
    struct HksBlob keyAlias1 = {strlen(keyAliasString1), (uint8_t *)keyAliasString1};
    struct HksBlob keyAlias2 = {strlen(keyAliasString2), (uint8_t *)keyAliasString2};

    if ((genParamSet1 != nullptr) || (signParamSet1 != nullptr) || (verifyParamSet1 != nullptr) || 
    (genParamSet2 != nullptr) || (signParamSet2 != nullptr) || (verifyParamSet2 != nullptr)) {
        ret = HksAcRsaSignVerifyTestCustomCase(keyAlias1, genParamSet1, signParamSet1, verifyParamSet1, secureUid1, enrolledId1, time1,
        keyAlias2, genParamSet2, signParamSet2, verifyParamSet2);
    }

    /* Delete Key */
    ret = HksDeleteKey(&keyAlias1, genParamSet1);
    EXPECT_EQ(ret, HKS_SUCCESS) << "DeleteKey failed.";
    ret = HksDeleteKey(&keyAlias2, genParamSet2);
    EXPECT_EQ(ret, HKS_SUCCESS) << "DeleteKey failed.";

    HksFreeParamSet(&genParamSet1);
    HksFreeParamSet(&signParamSet1);
    HksFreeParamSet(&verifyParamSet1);
    HksFreeParamSet(&genParamSet2);
    HksFreeParamSet(&signParamSet2);
    HksFreeParamSet(&verifyParamSet2);
}

}